package com.up.redis.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.util.StringUtils;

import java.util.function.Consumer;

/**
 * @author: baiMl
 * @title: RedissonAdapterConfiguration
 * @projectName: 海联技术中台V2.0
 * @depart 软件事业部
 * @description: 11-13 baiMl修改为手动开启Redisson
 * @date: 2022/5/19 15:06
 */
//@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Redisson.class)
public class RedissonAdapterConfiguration {

    private final String schema = "redis://%s";

    private final RedissonProperties redissonProperties;

    public RedissonAdapterConfiguration(RedissonProperties redissonProperties) {
        this.redissonProperties = redissonProperties;
    }

    /**
     * 单机模式
     *
     * @return
     */
    @Bean
    @ConditionalOnProperty(prefix = "redisson.client", value = "mode", havingValue = "single")
    public RedissonClient singleRedisson() {
        String addrFormat = "redis://%s:%d";
        Config config = new Config();
        RedissonProperties.Single single = redissonProperties.getSingle();
        String redisAddr = String.format(addrFormat, single.getIp(), single.getPort());
        SingleServerConfig singleServerConfig = config.useSingleServer()
                .setPingConnectionInterval(redissonProperties.getPingTimeout())
                .setTimeout(redissonProperties.getTimeout())
                .setDatabase(single.getDatabase())
                .setRetryAttempts(redissonProperties.getRetryAttempts())
                .setConnectTimeout(redissonProperties.getConnectTimeout())
                .setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout())
                .setRetryInterval(redissonProperties.getRetryInterval())
                .setAddress(redisAddr);
        setPassword(singleServerConfig::setPassword);
        return Redisson.create(config);
    }

    private void setPassword(Consumer<String> consumer) {
        String password = redissonProperties.getPassword();
        if (!StringUtils.isEmpty(password)) {
            consumer.accept(password);
        }
    }

    /**
     * 集群模式
     *
     * @return
     */
    @Bean
    @ConditionalOnProperty(prefix = "redisson.client", value = "mode", havingValue = "cluster")
    public RedissonClient clusterRedisson() {
        Config config = new Config();
        RedissonProperties.Cluster cluster = redissonProperties.getCluster();
        if (cluster == null) {
            throw new BeanInstantiationException(RedissonClient.class, "cluster nodes is null");
        }
        ClusterServersConfig clusterServersConfig = config.useClusterServers()
                .setPingConnectionInterval(redissonProperties.getPingTimeout())
                .setTimeout(redissonProperties.getTimeout())
                .setRetryAttempts(redissonProperties.getRetryAttempts())
                .setConnectTimeout(redissonProperties.getConnectTimeout())
                .setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout())
                .setRetryInterval(redissonProperties.getRetryInterval())
                .addNodeAddress(cluster.getNodes().stream().map(item -> String.format(schema, item)).toArray(String[]::new));
        setPassword(clusterServersConfig::setPassword);
        return Redisson.create(config);
    }
}
